/* -*- c++ -*- */
/*
 * This file is part of the SD Project.
 *
 * Authors: Cleiber Marques da Silva <cleiber@lisha.ufsc.br>
 * 			Odilson Tadeu Valle <odilson@sj.ifsc.edu.br>
 * 
 * SD Project is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; version 2 of the License.
 */

#include <iostream>
#include <cmath>

#include "listener_impl.h"

namespace sd {
	listener_impl::listener_impl(sd::clock *_clock, sd::delivery *_delivery)
	{
		clock = _clock;
		delivery = _delivery;
	}

	void listener_impl::listen(const CORBA::Any& a)
	{
  		struct_message *tp;
		if (a >>= tp){
			// Copy message to your delivery buffer
			int id = tp->id - 1;
			delivery->messages[id].push(tp);

			/*cout << "type = " << tp->type << endl;
			cout << "id = " << tp->id << endl;
			cout << "seq = " << tp->seq << endl;
			cout << "mesg = " << tp->mesg << endl;*/

			// Update clock of emitter
			int timestamp = tp->timestamp[id];
			clock->mutex.lock();
			clock->update_timestamp(id, std::max(timestamp, clock->get_timestamp(id)));
			clock->mutex.unlock();

			/*cout << "timestamp = <";
			cout << clock->get_timestamp(0) << ", ";
			cout << clock->get_timestamp(1) << ", " ;
			cout << clock->get_timestamp(2) << ">" << endl;*/

			// Call the tool for delivery messages
			tool(id);
	}
	else
		std::cout << "Unknown value." << std::endl;
	}

	void listener_impl::tool(int id)
	{
		while(struct_message *m = delivery->messages[id].front()) {
			bool ok = true;
			// Verify clock->i[k] >= clock->j[k] to k != id
			for(unsigned int i = 0; i < clock->timestamp.size(); i++) {
				if (id == i)
					continue;
				if (!(m->timestamp[i] >= clock->get_timestamp(i))) {
					ok = false;
					break;
				}
			}

			if (ok) {
				std::string mesg = std::string(m->mesg);
				std::cout << mesg << " id = " << m->id << std::endl;
				delivery->mutex.lock();
				delivery->casual.push_back(*m);
				delivery->mutex.unlock();
				delivery->messages[id].pop();
				delivery->window_show();
			} else
				break;
		}
	}
}
